﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using NLog;
using QPlcPlayer.Models;
using QPlcPlayer.Services;

namespace QPlcPlayer
{
	public static class AppRuntime
	{
		public static Lazy<NLog.Logger> Logger = new Lazy<NLog.Logger>(() =>
		{
			var logger = NLog.LogManager.GetCurrentClassLogger();
			return logger;
		});

		static AppRuntime()
		{
			InitCarNumber();
			InitFeedRate();			
			InitService();
			
			
			

		}

		/// <summary>
		/// 定时器状态
		/// </summary>
		public static QTimerStatus QTimerStatus { get; set; }
		public static decimal BigPigeon { get; set; }
		public static List<decimal> SmallPigeon { set; get; } = new List<decimal>();
		public static List<string> Areas { get; set; } = new List<string>();

		public static string DbConnectionString { get; set; }
		private static IServiceProvider Services { get; set; }
		public static IServiceProvider GetService()
		{
			if (Services == null) InitService();
			if (string.IsNullOrWhiteSpace(CarNumber)) InitCarNumber();
			if (SmallPigeon == null || SmallPigeon.Count <= 0) InitFeedRate();
			if (QTimerStatus == null) QTimerStatus = Services.GetService<QTimerStatusService>().GetQTimerStatus(AppRuntime.CarNumber);
			
			return Services;
		}

		public static string CarNumber { get; set; }
		

		public static TodayDosingSchedule TodayDosingSchedule { get; set; }
		private static DosingSchedule DosingSchedule { get; set; }
		public static DosingSchedule GetDosingSchedule()
		{
			if (DosingSchedule == null)
			{
				var car = AppRuntime.GetService().GetService<AgvCarService>().GetAgvCarByNumber(AppRuntime.CarNumber);
				var schedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetDosingScheduleByCarId(car.ID);
				DosingSchedule = schedule;
			}
			return DosingSchedule;
		}
		public static DosingSchedule GetDosingScheduleAndUpdate()
		{
			var car = AppRuntime.GetService().GetService<AgvCarService>().GetAgvCarByNumber(AppRuntime.CarNumber);
			var schedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetDosingScheduleByCarId(car.ID);
			DosingSchedule = schedule;
			return DosingSchedule;
		}




		public static void UpdateData()
		{
			InitFeedRate();
			InitCarNumber();
			TodayDosingSchedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetTodayDosingSchedulePlus();
			var car = AppRuntime.GetService().GetService<AgvCarService>().GetAgvCarByNumber(AppRuntime.CarNumber);
			var schedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetDosingScheduleByCarId(car.ID);
			KKSchedule.Add(80, new int[] { schedule.First_80, schedule.Second_80, schedule.Third_80 });
			KKSchedule.Add(120, new int[] { schedule.First_120, schedule.Second_120, schedule.Third_120 });
			KKSchedule.Add(160, new int[] { schedule.First_160, schedule.Second_160, schedule.Third_160 });
			KKSchedule.Add(200, new int[] { schedule.First_200, schedule.Second_200, schedule.Third_200 });
			DosingSchedule = schedule;
		}

		/// <summary>
		/// 初始化喂料量
		/// </summary>
		private static void InitFeedRate()
		{
			var bigPigeonStr = ConfigurationManager.AppSettings.Get("BigPigeon");
			var smallPigeonStr = ConfigurationManager.AppSettings.Get("SmallPigeon");
			decimal.TryParse(bigPigeonStr, out var val);
			BigPigeon = val;
			smallPigeonStr.Split(',').ToList().ForEach(x =>
			{
				decimal.TryParse(x, out var y);
				SmallPigeon.Add(y);
			});

			var areastr = ConfigurationManager.AppSettings.Get("Area");
			areastr.Split(',').ToList().ForEach(x =>
			{
				Areas.Add(x);
			});




		}
		private static void InitCarNumber()
		{
			var carNUmber = ConfigurationManager.AppSettings.Get("CarNumber");
			CarNumber = carNUmber ?? "1";
		}
		
		public static void InitKKSchedule()
		{
			var car = AppRuntime.GetService().GetService<AgvCarService>().GetAgvCarByNumber(AppRuntime.CarNumber);
			var schedule = AppRuntime.GetService().GetService<DosingScheduleService>().GetDosingScheduleByCarId(car.ID);
			KKSchedule.Add(80, new int[] { schedule.First_80, schedule.Second_80, schedule.Third_80 });
			KKSchedule.Add(120, new int[] { schedule.First_120, schedule.Second_120, schedule.Third_120 });
			KKSchedule.Add(160, new int[] { schedule.First_160, schedule.Second_160, schedule.Third_160 });
			KKSchedule.Add(200, new int[] { schedule.First_200, schedule.Second_200, schedule.Third_200 });
		}
		private static void InitService()
		{

			var services = new ServiceCollection();
			services.AddTransient<DosingScheduleService>();
			services.AddTransient<AgvCarService>();
			services.AddTransient<PigeonCageService>();
			services.AddTransient<PigeonChildService>();
			services.AddTransient<PigeonEggService>();
			services.AddTransient<DailyPatrolInspectionService>();
			services.AddTransient<QTimerStatusService>();
			Services = services.BuildServiceProvider();
		}


		public static QPlcManager PlcManager { get; set; } = new QPlcManager();
		public static QPlcManager GetPlcManager()
		{
			if(PlcManager==null) PlcManager = new QPlcManager();
			return PlcManager;
		}

		public static Dictionary<int, int[]> KKSchedule = new Dictionary<int, int[]>();

		public static void InteractionPLC()
		{
			try
			{
				var pigeonCageId =GetPlcManager().GetBarCode();
				var pigeoncage = TodayDosingSchedule.PigeonCages.FirstOrDefault(x => x.ID == pigeonCageId);
				if (pigeoncage == null) return;

				var first_column = pigeoncage.Arrange;
				var sceond_column = "";
				int.TryParse(first_column, out var nextcolumn);
				if (nextcolumn % 2 == 0) sceond_column = (nextcolumn - 1).ToString("D2");
				else sceond_column = (nextcolumn + 1).ToString("D2");

				int[] plcdata = new int[8];
				for (int i = 0; i < TodayDosingSchedule.PigeonCages.Count; i++)
				{
					var tt = TodayDosingSchedule.PigeonCages[i];
					if (tt.Building != pigeoncage.Building) continue;
					if (tt.Arrange != first_column && tt.Arrange != sceond_column) continue;
					if (tt.Building == pigeoncage.Building && tt.Arrange == pigeoncage.Arrange && tt.Group == pigeoncage.Group)
					{
						if (tt.Number == "01")
						{
							plcdata[0] = TodayDosingSchedule.OKSchedues[tt.ID];
						}
						else if (tt.Number == "02")
						{
							plcdata[1] = TodayDosingSchedule.OKSchedues[tt.ID];
						}
						else if (tt.Number == "03")
						{
							plcdata[2] = TodayDosingSchedule.OKSchedues[tt.ID];
						}
						else if (tt.Number == "04")
						{
							plcdata[3] = TodayDosingSchedule.OKSchedues[tt.ID];
						}
					}
					else if (tt.Building == pigeoncage.Building && tt.Arrange == sceond_column && tt.Group == pigeoncage.Group)
					{
						if (tt.Number == "01")
						{
							plcdata[4] = TodayDosingSchedule.OKSchedues[tt.ID];
						}
						else if (tt.Number == "02")
						{
							plcdata[5] = TodayDosingSchedule.OKSchedues[tt.ID];
						}
						else if (tt.Number == "03")
						{
							plcdata[6] = TodayDosingSchedule.OKSchedues[tt.ID];
						}
						else if (tt.Number == "04")
						{
							plcdata[7] = TodayDosingSchedule.OKSchedues[tt.ID];
						}
					}
				}

				var isfirst = DateTime.Now >= TodayDosingSchedule.FirstTime && DateTime.Now < TodayDosingSchedule.SecondTime;
				var issecond = DateTime.Now >= TodayDosingSchedule.FirstTime && DateTime.Now < TodayDosingSchedule.ThirdTime;
				var isthird = DateTime.Now >= TodayDosingSchedule.ThirdTime;
				for (int i = 0; i < plcdata.Length; i++)
				{
					if (isfirst)
					{
						plcdata[i] = KKSchedule[plcdata[i]][0];
					}
					else if (issecond)
					{
						plcdata[i] = KKSchedule[plcdata[i]][1];
					}
					else
					{
						plcdata[i] = KKSchedule[plcdata[i]][2];
					}
				}

				GetPlcManager().上位机喂料量下达(plcdata);
			}
			catch (Exception ex)
			{
				Logger_Error(ex.Message);
			}

		}

		public static HashSet<string> PLCCache { get; set; } = new HashSet<string>();
		public static (bool IsOK, string PigeonCageId,string err) InteractionPLC(bool IsFirst, bool IsSecond, bool IsThird)
		{
			var pigeonCageId = string.Empty;
			try
			{
				pigeonCageId = GetPlcManager().GetBarCode();//"00e1f804-d5c7-4929-9206-cf5eabac3146";

				if (string.IsNullOrWhiteSpace(pigeonCageId)) return (false, pigeonCageId,"");
				if (PLCCache.Contains(pigeonCageId))
				{
					return (false, pigeonCageId,"");
				}
				if (TodayDosingSchedule.CagesRelations.ContainsKey(pigeonCageId))
				{
					var keyval = TodayDosingSchedule.CagesRelations[pigeonCageId];
					var res = TodayDosingSchedule.CagesFeeds[keyval];
					var newres = new int[res.Length];
					for (int i = 0; i < res.Length; i++) newres[i] = res[i];
					GetFeedSceduleRate(ref newres, IsFirst, IsSecond, IsThird);
					GetPlcManager().上位机喂料量下达(newres);
					var msg = $"--------{pigeonCageId}____{keyval}_____[{string.Join(",", newres)}]";
					Logger_Info(msg);
				}
				PLCCache.Add(pigeonCageId);
				return (true, pigeonCageId,"");
			}
			catch (Exception ex)
			{
				Logger_Error(ex.Message);
				return (false, pigeonCageId,ex.Message);
			}

		}
		private static void GetFeedSceduleRate(ref int[] values, bool IsFirst, bool IsSecond, bool IsThird)
		{
			if (values == null || values.Length == 0) return;
			for (int i = 0; i < values.Length; i++)
			{
				if (IsFirst) values[i] = KKSchedule[values[i]][0];
				else if (IsSecond) values[i] = KKSchedule[values[i]][1];
				else if (IsThird) values[i] = KKSchedule[values[i]][2];
			}
		}

		public static bool InteractionPLCByQ(bool IsFirst, bool IsSecond, bool IsThird)
		{
			try
			{
				var pigeonCageId = GetPlcManager().GetBarCode();//A0100202-0000-0000-0000-000000000000
				if (string.IsNullOrWhiteSpace(pigeonCageId)) return false;
				if (TodayDosingSchedule.CagesRelations.ContainsKey(pigeonCageId))
				{
					var building = pigeonCageId[0];
					var arrange = pigeonCageId.Substring(1, 2);
					var group = pigeonCageId.Substring(3, 3);
					int.TryParse(arrange, out int arrangeInt);
					var isOdd = arrangeInt % 2 != 0;
					if (arrangeInt % 2 == 0) arrangeInt -= 1;
					var tt = pigeonCageId.ToArray();
					var newres = new int[8];
					for (int i = 1; i <= 4; i++)
					{
						var number = i.ToString("D2");
						tt[6] = number[0];
						tt[7] = number[1];
						var firstLine = arrangeInt.ToString("D2");
						tt[1] = firstLine[0];
						tt[2] = firstLine[1];
						var id_0 = tt.ToString();

						var secondLine = (arrangeInt + 1).ToString("D2");
						tt[1] = firstLine[0];
						tt[2] = firstLine[1];
						var id_1 = tt.ToString();
						if (AppRuntime.TodayDosingSchedule.OKSchedues.ContainsKey(id_0)) newres[i - 1] = AppRuntime.TodayDosingSchedule.OKSchedues[id_0];
						if (AppRuntime.TodayDosingSchedule.OKSchedues.ContainsKey(id_1)) newres[i + 3] = AppRuntime.TodayDosingSchedule.OKSchedues[id_1];

					}

					GetFeedSceduleRate(ref newres, IsFirst, IsSecond, IsThird);
					GetPlcManager().上位机喂料量下达(newres);

					var msg = $"--------{pigeonCageId}____[{string.Join(",", newres)}]";
					Logger_Info(msg);
				}
				return true;
			}
			catch (Exception ex)
			{
				Logger_Error(ex.Message);
				return false;
			}
		}

		public static void Logger_Info(string msg)
		{
			if (QTimerStatus!=null && QTimerStatus.IsLogger)
			{
				Logger.Value.Info(msg);
			}
			
		}
		public static void Logger_Error(string msg)
		{
			if (QTimerStatus != null && QTimerStatus.IsLogger)
			{
				Logger.Value.Error(msg);
			}
				
		}

	}
}
